﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Utility3D.Extensions
{
    public static class TypeExtensions
    {
        public static bool IsListType(this Type source)
        {
            return false;
        }

        private static HashSet<Type> _convertibleTypes = GetConvertibleTypes();

        private static HashSet<Type> GetConvertibleTypes()
        {
            var hashSet = new HashSet<Type>();
            var convertibleTypes = typeof (Convert)
                .GetMethods()
                .Where(method => method.GetParameters().Count() == 1 && method.Name == "ToString")
                .Select(method => method.GetParameters().First().ParameterType);
            foreach (var type in convertibleTypes)
                hashSet.Add(type);
            return hashSet;
        }

        public static bool IsSystemType(this Type source)
        {
            return _convertibleTypes.Contains(source);
        }

        public static Action<object, object> GetSetter<TType, TProperty>(this Type source, Expression<Func<TType, TProperty>> expression)
        {
            var memberExpression = expression.Body as MemberExpression;
            if (memberExpression == null) throw new Exception(string.Format("Could not parse expression: '{0}'", expression));

            return source.GetMember(memberExpression.Member.Name).Single().GetSetter();
        }

        public static IEnumerable<Type> GetGenericArgumentsForType(this Type source, Type baseType)
        {
            return source
                .ChainWithSelf(type => type.BaseType)
                .SelectMany(type => new[] {type}.Concat(type.GetInterfaces()))
                .Where(type => type.IsGenericType)
                .Single(type => type.GetGenericTypeDefinition() == baseType)
                .GetGenericArguments();
        }
    }
}